﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Xml.Linq;

using umbraco.BasePages;
using umbraco.IO;
using System.Xml.XPath;
using umbraco;
using umbraco.cms.businesslogic.propertytype;
using umbraco.cms.businesslogic.web;
using DigibizTree;
using umbraco.BusinessLogic;
using System.Xml;
using umbraco.DataLayer;
using System.Text;
using umbraco.cms.businesslogic.media;
using System.Data.SqlClient;
using System.Data;

namespace DigibizAdvancedMediaPicker
{
    public partial class DigibizAdvancedMediaPicker : UserControl, IMediaPicker
    {
        #region Properties

        #region IMediaPicker Members

        public string SaveValue
        {
            get;
            set;
        }

        public string AllowedExtensionsValue
        {
            get;
            set;
        }

        public string AllowedSelectableMediaTypesValue
        {
            get;
            set;
        }

        public string AllowedCreateableMediaTypesValue
        {
            get;
            set;
        }

        public int DefaultMediaTypeValue
        {
            get;
            set;
        }

        public bool HideCreateValue
        {
            get;
            set;
        }

        public int StartNodeIdValue
        {
            get;
            set;
        }

        public bool SelectMultipleNodesValue
        {
            get;
            set;
        }

        public int MinimumNodesValue
        {
            get;
            set;
        }

        public int MaximumNodesValue
        {
            get;
            set;
        }

        public string CropPropertyAliasValue
        {
            get;
            set;
        }

        public string CropNameValue
        {
            get;
            set;
        }

        public int ThumbnailWidthValue
        {
            get;
            set;
        }

        public int ThumbnailHeightValue
        {
            get;
            set;
        }

        public bool HideEditValue
        {
            get;
            set;
        }

        public bool HideOpenValue
        {
            get;
            set;
        }

        public bool HidePixlrValue
        {
            get;
            set;
        }

        public bool EnableSearch
        {
            get;
            set;
        }

        public bool EnableSearchAutoSuggest
        {
            get;
            set;
        }

        public string SearchMethod
        {
            get;
            set;
        }

        public bool Mandatory
        {
            get;
            set;
        }

        public bool CheckValidation
        {
            get;
            set;
        }

        public string MinimumNodesText
        {
            get;
            set;
        }

        public string MaximumNodesText
        {
            get;
            set;
        }

        public string MandatoryText
        {
            get;
            set;
        }

        public int DataTypeDefinitionId
        {
            get;
            set;
        }

        /// <summary>
        /// Determines if the save button is pressed or when the page is loaded for the first time.
        /// </summary>
        private bool IsSave
        {
            get;
            set;
        }

        public object Value
        {
            get
            {
                try
                {
                    IsSave = true;

                    List<DAMP_MediaItem> mediaItemsList = new List<DAMP_MediaItem>();
                    object returnValue = DataBindMedia(out mediaItemsList);

                    //This boolean is to check if this datatype is still valid. If it isn't it's not neccesary to do other checks.
                    bool isValid = true;

                    if (CheckValidation)
                    {
                        if (SelectMultipleNodesValue)
                        {
                            //Show an error if the not enough media items are selected.
                            if (isValid && MinimumNodesValue != -1 && mediaItemsList.Count < MinimumNodesValue)
                            {
                                isValid = false;
                                LitError.Text = MinimumNodesText;
                                LitError.Visible = true;
                                DAMP_Validation.ShowError(LitError.Text);
                            }

                            //Show an error if too much media items are selected.
                            if (isValid && MaximumNodesValue != -1 && mediaItemsList.Count > MaximumNodesValue)
                            {
                                isValid = false;
                                LitError.Text = MaximumNodesText;
                                LitError.Visible = true;
                                DAMP_Validation.ShowError(LitError.Text);
                            }
                        }

                        if (isValid && Mandatory && mediaItemsList.Count == 0)
                        {
                            //If the propertytype is mandatory and no item is selected show an error message.
                            isValid = false;
                            LitError.Text = MandatoryText;
                            LitError.Visible = true;
                            DAMP_Validation.ShowError(LitError.Text);
                        }
                    }

                    //Return the selected items as XDocument or string.
                    return returnValue;
                }
                catch (Exception ex)
                {
                    DAMP_Helper.LogException(ex);
                }

                return null;
            }
            set
            {
                try
                {
                    IsSave = true;

                    if (value != null)
                    {
                        List<DAMP_MediaItem> mediaItemsList = new List<DAMP_MediaItem>();

                        //Convert the xml or string into List<DAMP_MediaItem>.
                        if (StoreAsXML)
                        {
                            mediaItemsList = ConvertXML(value.ToString());
                        }
                        else
                        {
                            char[] charSeparators = new char[] { ',' };
                            string[] ids = value.ToString().Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);

                            //Get the selected items as XDocument.
                            XDocument xmlDocument = DigibizMediaHelper.GetXML(ids);

                            if (xmlDocument != null)
                            {
                                mediaItemsList = ConvertXML(xmlDocument);
                            }
                        }

                        //Show the media items.
                        ListViewMediaItem.DataSource = mediaItemsList;
                        ListViewMediaItem.DataBind();

                    }
                }
                catch (Exception ex)
                {
                    DAMP_Helper.LogException(ex);
                }
            }
        }

        #endregion

        public bool StoreAsXML
        {
            get
            {
                return this.SaveValue == "fullMedia";
            }
        }

        /// <summary>
        /// Gets a unique ID based on the date/time, used to append to images so they don't cache after updating via edit popup or elsewhere.
        /// </summary>
        public string UniqueID
        {
            get
            {
                DateTime date = DateTime.Now;

                string uniqueID = String.Format(
                  "{0:0000}{1:00}{2:00}{3:00}{4:00}{5:00}{6:000}",
                  date.Year, date.Month, date.Day,
                  date.Hour, date.Minute, date.Second, date.Millisecond
                  );
                return uniqueID;
            }
        }

        #endregion

        protected void Page_Load(object sender, EventArgs e)
        {
            pnlCreateButton.Visible = !HideCreateValue;
        }

        protected override void OnPreRender(EventArgs e)
        {
            base.OnPreRender(e);

            //If a normal postback is triggered (not the save button) we need to store the javascript changes.
            if (!IsSave)
            {
                List<DAMP_MediaItem> mediaItemsList = new List<DAMP_MediaItem>();
                DataBindMedia(out mediaItemsList);
            }
        }

        /// <summary>
        /// DataBind the media to the ListViewMediaItem and return the value used for storing the data.
        /// </summary>
        /// <param name="mediaItemsList"></param>
        /// <returns></returns>
        private object DataBindMedia(out List<DAMP_MediaItem> mediaItemsList)
        {
            mediaItemsList = new List<DAMP_MediaItem>();
            object returnValue = null;
            LitError.Visible = false;

            char[] charSeparators = new char[] { ',' };
            string[] ids = HiddenFieldIds.Value.Split(charSeparators, StringSplitOptions.RemoveEmptyEntries);

            //Get the selected items as XDocument.
            XDocument xmlDocument = DigibizMediaHelper.GetXML(ids);

            if (xmlDocument != null)
            {
                //Convert the xml into a List again because we need to databind the values again.
                mediaItemsList = ConvertXML(xmlDocument);
            }

            //Display the items again after the postback.
            ListViewMediaItem.DataSource = mediaItemsList;
            ListViewMediaItem.DataBind();

            if (StoreAsXML)
            {
                //Store the XDocument in the value which will be returned.
                returnValue = xmlDocument;
            }
            else
            {
                //Store the string in the value which will be returned.
                returnValue = HiddenFieldIds.Value.TrimStart(',').TrimEnd(',');
            }

            return returnValue;
        }

        protected void ListViewMediaItem_ItemDataBound(object sender, ListViewItemEventArgs e)
        {
            Literal ltlImagePreview = (Literal)e.Item.FindControl("ltlImagePreview");
            DAMP_MediaItem currentMedia = (DAMP_MediaItem)e.Item.DataItem;
            
            ltlImagePreview.Text = DigibizMediaHelper.ShowImage(currentMedia.MediaLink,
                this.ThumbnailWidthValue, 
                this.ThumbnailHeightValue, 
                currentMedia.MediaId,
                cssClass: "dragHandle", 
                crop: currentMedia.MediaCrop,
                icon: currentMedia.MediaUrl);
        }

        /// <summary>
        /// Convert the string into xml and convert the xml into List<DAMP_MediaItem> with all the required data.
        /// </summary>
        /// <param name="value"></param>
        /// <returns></returns>
        private List<DAMP_MediaItem> ConvertXML(string value)
        {
            if (!string.IsNullOrEmpty(value))
            {
                XDocument xmlDocument = XDocument.Parse(value);

                return ConvertXML(xmlDocument);
            }

            return new List<DAMP_MediaItem>();
        }

        /// <summary>
        /// Convert the xml into List<DAMP_MediaItem> with all the required data.
        /// </summary>
        /// <param name="xmlDocument"></param>
        /// <returns></returns>
        private List<DAMP_MediaItem> ConvertXML(XDocument xmlDocument)
        {
            try
            {
                List<DAMP_MediaItem> dampMediaItemList =
                    (
                        from mediaItemElement in xmlDocument.Descendants("mediaItem")
                        let firstNode = (XElement)mediaItemElement.FirstNode
                        let id = DigibizMediaHelper.GetMediaId(firstNode)
                        where DigibizMediaHelper.MediaExists(id.ToString())
                        select new DAMP_MediaItem
                            (
                                id,
                                DigibizMediaHelper.GetMediaLink(firstNode),
                                DigibizMediaHelper.GetMediaIcon(firstNode),
                                DigibizMediaHelper.GetMediaName(firstNode),
                                DigibizMediaHelper.GetMediaCrop(firstNode, CropPropertyAliasValue, CropNameValue)
                            )
                    ).ToList();

                return dampMediaItemList;
            }
            catch (Exception ex)
            {
                DAMP_Helper.LogException(ex);
                return new List<DAMP_MediaItem>();
            }
        }

    }
}